iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 24
0
自我挑戰組

React 30 天學習歷程系列 第 24

【Day 24】React Hook(一): Hook 簡介 及 useState、useEffect 使用

  • 分享至 

  • xImage
  •  

React Hook 是 React 16.8 中新增的功能,它解決了以下幾個問題:

  • 讓開發者不必使用 class 也能使用 state 和 React 其他的功能,使得 function component 能更有效的被使用。
  • 通常只要我們進行遠端資料獲取、手動修改 DOM 等行為,都會產生 side effect(副作用)。在 class component 中,我們透過 componentDidMountcomponentDidUpdatecomponentWillUnmount 這幾個方法來處理 side effect。透過 React Hook,我們在 function component 中只要利用一個叫 useEffect 的方法即可處理,更為簡便易用。
  • React Hook 解決了很多程式碼重複使用的問題。在專案開發中通常會有許多共用元件,例如按鈕、表單、彈出視窗等,另外也有一些需要重複使用的資料請求或取消功能。這些重複的功能過去我們只能用 class component 來封裝,但在有了 React Hook 後,我們可以利用更為簡便的 function component 來進行封裝。
  • 過去處理比較複雜的狀態管理,通常都會使用第三方套件,但是現在也可以選擇透過 React Hook 中的 useReduceruseContext 功能做處理。
  • React Hook 搭配 function component 的學習及使用體驗都更好,應用性能也較好。官網文件中有提到 class 在學習及使用上都更為複雜,class component 對於目前的一些開發工具來說也不好壓縮。

useState

useState 能讓 function component 使用 state,下面是它的一個基本使用方式。useState 中有一個參數initState,是初始的 stateinitState可以是任意類型的值,也可以是一個回調函式,但必須有返回值。我們調用 useState 後會返回一個陣列,陣列內的兩個值 state 是我們要設置的狀態,setState 是更新陣列內 state 的函式。

const [state, setState] = useState(initState)

下面為一個簡單的加數字功能範例,我們使用 useState 來設定 state、更新方法及初始值,透過 onClick 觸發 setCount 去改變 state

// 引用 useEffect
import { useState } from 'react';

const Test = () => {
    // 設定 state、更新方法及初始值
    const [count, setCount] = useState(0)

    return <div>
        <div>{ count }</div>
        <div><button onClick={ () => setCount(count + 1) }>click</button></div>
    </div>
}

useEffect

useEffect 如前面所述,是用來處理 side effect 用的,也是 componentDidMountcomponentDidUpdatecomponentWillUnmount 三個函式的統一。它接受兩個參數,callbackarraycallback 是我們處理 side effect 的回調函式,array是決定 useEffect 的執行。useEffect 是在元件第一次 render 和每次 render 時會執行

callback 處理 side effect

所有的 side effect 行為都應該在 useEffect 裡面處理,另外也可以透過返回一個函式來進行清理,如下面的 return,它會在元件卸載時候自動調用,相當於 class component 的 componentWillUnmount

useEffect(() => {
    // side effect 
    return () => {
        // 清理工作,類似 componentWillUnmount
    }
})

array 控制執行

array 參數控制 useEffect 的執行,如果是空陣列,就只會在元件第一次 render 後執行,相當於 componentDidMount,如果陣列內有值,那會在陣列內的值發生改變後執行。還有一種情況是沒有 array 參數,那 useEffect 就會在每一次 render 後都執行一次。陣列內的值可以是元件內的 state,或是元件外傳入的 props

useEffect(() => {
    // side effect 
}, []) // 第一次 render 時,執行一次

useEffect(() => {
    // side effect 
}, [count]) // 陣列內的值發生變化時執行

useEffect(() => {
    // side effect 
}) // 每次次 render 時,都執行一次

下面的範例中,count 每次發生改變,useEffect 都會執行一次。

import { useState, useEffect } from 'react';

const Test = () => {
    // 設定 state、更新方法及初始值
    const [count, setCount] = useState(0)
    
    useEffect(() => {
        //手動修改 react dom
        document.title = `點擊了${count}次`
    }, [count])// count 每次改變,useEffect 都會執行一次

    return <div>
        <div>{ count }</div>
        <div><button onClick={ () => setCount(count + 1) }>click</button></div>
    </div>
}

同時使用多個 useEffect

我們也可以同時使用多個 useEffect,以下面的範例來說,我們就可以決定在不同時間點渲染時,去執行不同的事情。

const Test = () => {
    // 設定 state、更新方法及初始值
    const [count, setCount] = useState(0
    
    useEffect(() => {
        document.title = `還沒點擊`
    }, [])// 第一次 render 時執行
    
    useEffect(() => {
        // side effect 
        document.title = `點擊了${count}次`
    }, [count]) // count 每次改變,useEffect 都會執行

    return <div>
        <div>{ count }</div>
        <div><button onClick={ () => setCount(count + 1) }>click</button></div>
    </div>
}

在 useEffect 進行遠端資料請求

我們也可以在 useEffect 進行遠端資料請求,如下面利用空陣列,在第一次 render 時請求資料

const Test = () => {
    // 設定 state、更新方法及初始值
    const [data, setData] = useState(0
    
    const fetchData = async () => {
        const result = await fetch('./user.json').then(res => res.json())
        setData()
    }
    
    useEffect(() => {
        //手動修改 react dom
        fetchData()
    }, [])// count 每次改變,useEffect 都會執行一次

    return <div>
        <div>{ data }</div>
    </div>
}

useEffect 清理機制

React 中有兩種常見的 side effect 類型,一種需要清理,一種不需要,如下

  • 遠端資料請求、DOM 修改等不需要清理,useEffect 會在每次執行之前,自動清理之前的 side effect。
  • 訂閱和取消訂閱、監聽事件和取消監聽這種都需要清理,需要向前面使用的例子,用回調函式進行清理。

上一篇
【Day 23】React 的高級特性
下一篇
【Day 25】React Hook(二): Context 和 useContext
系列文
React 30 天學習歷程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
TD
iT邦新手 4 級 ‧ 2020-10-07 11:44:32

Yeah I love hooks~~

我要留言

立即登入留言